1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
21
22 import com.google.common.annotations.Beta;
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.base.Supplier;
25
26 import java.io.Serializable;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Comparator;
30 import java.util.EnumMap;
31 import java.util.EnumSet;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.LinkedHashMap;
35 import java.util.LinkedHashSet;
36 import java.util.LinkedList;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.SortedSet;
41 import java.util.TreeMap;
42 import java.util.TreeSet;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 @Beta
70 @GwtCompatible
71 public abstract class MultimapBuilder<K0, V0> {
72
73
74
75
76
77 private MultimapBuilder() {}
78
79 private static final int DEFAULT_EXPECTED_KEYS = 8;
80
81
82
83
84 public static MultimapBuilderWithKeys<Object> hashKeys() {
85 return hashKeys(DEFAULT_EXPECTED_KEYS);
86 }
87
88
89
90
91
92
93
94 public static MultimapBuilderWithKeys<Object> hashKeys(final int expectedKeys) {
95 checkNonnegative(expectedKeys, "expectedKeys");
96 return new MultimapBuilderWithKeys<Object>() {
97 @Override
98 <K, V> Map<K, Collection<V>> createMap() {
99 return new HashMap<K, Collection<V>>(expectedKeys);
100 }
101 };
102 }
103
104
105
106
107
108
109
110
111
112 public static MultimapBuilderWithKeys<Object> linkedHashKeys() {
113 return linkedHashKeys(DEFAULT_EXPECTED_KEYS);
114 }
115
116
117
118
119
120
121
122
123
124
125 public static MultimapBuilderWithKeys<Object> linkedHashKeys(final int expectedKeys) {
126 checkNonnegative(expectedKeys, "expectedKeys");
127 return new MultimapBuilderWithKeys<Object>() {
128 @Override
129 <K, V> Map<K, Collection<V>> createMap() {
130 return new LinkedHashMap<K, Collection<V>>(expectedKeys);
131 }
132 };
133 }
134
135
136
137
138
139
140
141
142
143
144
145 @SuppressWarnings("rawtypes")
146 public static MultimapBuilderWithKeys<Comparable> treeKeys() {
147 return treeKeys(Ordering.natural());
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public static <K0> MultimapBuilderWithKeys<K0> treeKeys(final Comparator<K0> comparator) {
164 checkNotNull(comparator);
165 return new MultimapBuilderWithKeys<K0>() {
166 @Override
167 <K extends K0, V> Map<K, Collection<V>> createMap() {
168 return new TreeMap<K, Collection<V>>(comparator);
169 }
170 };
171 }
172
173
174
175
176 public static <K0 extends Enum<K0>> MultimapBuilderWithKeys<K0> enumKeys(
177 final Class<K0> keyClass) {
178 checkNotNull(keyClass);
179 return new MultimapBuilderWithKeys<K0>() {
180 @SuppressWarnings("unchecked")
181 @Override
182 <K extends K0, V> Map<K, Collection<V>> createMap() {
183
184
185 return (Map<K, Collection<V>>) new EnumMap<K0, Collection<V>>(keyClass);
186 }
187 };
188 }
189
190 private static final class ArrayListSupplier<V> implements Supplier<List<V>>, Serializable {
191 private final int expectedValuesPerKey;
192
193 ArrayListSupplier(int expectedValuesPerKey) {
194 this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
195 }
196
197 @Override
198 public List<V> get() {
199 return new ArrayList<V>(expectedValuesPerKey);
200 }
201 }
202
203 private enum LinkedListSupplier implements Supplier<List<Object>> {
204 INSTANCE;
205
206 public static <V> Supplier<List<V>> instance() {
207
208 @SuppressWarnings({"rawtypes", "unchecked"})
209 Supplier<List<V>> result = (Supplier) INSTANCE;
210 return result;
211 }
212
213 @Override
214 public List<Object> get() {
215 return new LinkedList<Object>();
216 }
217 }
218
219 private static final class HashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
220 private final int expectedValuesPerKey;
221
222 HashSetSupplier(int expectedValuesPerKey) {
223 this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
224 }
225
226 @Override
227 public Set<V> get() {
228 return new HashSet<V>(expectedValuesPerKey);
229 }
230 }
231
232 private static final class LinkedHashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
233 private final int expectedValuesPerKey;
234
235 LinkedHashSetSupplier(int expectedValuesPerKey) {
236 this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
237 }
238
239 @Override
240 public Set<V> get() {
241 return new LinkedHashSet<V>(expectedValuesPerKey);
242 }
243 }
244
245 private static final class TreeSetSupplier<V> implements Supplier<SortedSet<V>>, Serializable {
246 private final Comparator<? super V> comparator;
247
248 TreeSetSupplier(Comparator<? super V> comparator) {
249 this.comparator = checkNotNull(comparator);
250 }
251
252 @Override
253 public SortedSet<V> get() {
254 return new TreeSet<V>(comparator);
255 }
256 }
257
258 private static final class EnumSetSupplier<V extends Enum<V>>
259 implements Supplier<Set<V>>, Serializable {
260 private final Class<V> clazz;
261
262 EnumSetSupplier(Class<V> clazz) {
263 this.clazz = checkNotNull(clazz);
264 }
265
266 @Override
267 public Set<V> get() {
268 return EnumSet.noneOf(clazz);
269 }
270 }
271
272
273
274
275
276
277
278 public abstract static class MultimapBuilderWithKeys<K0> {
279
280 private static final int DEFAULT_EXPECTED_VALUES_PER_KEY = 2;
281
282 MultimapBuilderWithKeys() {}
283
284 abstract <K extends K0, V> Map<K, Collection<V>> createMap();
285
286
287
288
289 public ListMultimapBuilder<K0, Object> arrayListValues() {
290 return arrayListValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
291 }
292
293
294
295
296
297
298
299 public ListMultimapBuilder<K0, Object> arrayListValues(final int expectedValuesPerKey) {
300 checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
301 return new ListMultimapBuilder<K0, Object>() {
302 @Override
303 public <K extends K0, V> ListMultimap<K, V> build() {
304 return Multimaps.newListMultimap(
305 MultimapBuilderWithKeys.this.<K, V>createMap(),
306 new ArrayListSupplier<V>(expectedValuesPerKey));
307 }
308 };
309 }
310
311
312
313
314 public ListMultimapBuilder<K0, Object> linkedListValues() {
315 return new ListMultimapBuilder<K0, Object>() {
316 @Override
317 public <K extends K0, V> ListMultimap<K, V> build() {
318 return Multimaps.newListMultimap(
319 MultimapBuilderWithKeys.this.<K, V>createMap(),
320 LinkedListSupplier.<V>instance());
321 }
322 };
323 }
324
325
326
327
328 public SetMultimapBuilder<K0, Object> hashSetValues() {
329 return hashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
330 }
331
332
333
334
335
336
337
338 public SetMultimapBuilder<K0, Object> hashSetValues(final int expectedValuesPerKey) {
339 checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
340 return new SetMultimapBuilder<K0, Object>() {
341 @Override
342 public <K extends K0, V> SetMultimap<K, V> build() {
343 return Multimaps.newSetMultimap(
344 MultimapBuilderWithKeys.this.<K, V>createMap(),
345 new HashSetSupplier<V>(expectedValuesPerKey));
346 }
347 };
348 }
349
350
351
352
353 public SetMultimapBuilder<K0, Object> linkedHashSetValues() {
354 return linkedHashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
355 }
356
357
358
359
360
361
362
363 public SetMultimapBuilder<K0, Object> linkedHashSetValues(final int expectedValuesPerKey) {
364 checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
365 return new SetMultimapBuilder<K0, Object>() {
366 @Override
367 public <K extends K0, V> SetMultimap<K, V> build() {
368 return Multimaps.newSetMultimap(
369 MultimapBuilderWithKeys.this.<K, V>createMap(),
370 new LinkedHashSetSupplier<V>(expectedValuesPerKey));
371 }
372 };
373 }
374
375
376
377
378 @SuppressWarnings("rawtypes")
379 public SortedSetMultimapBuilder<K0, Comparable> treeSetValues() {
380 return treeSetValues(Ordering.natural());
381 }
382
383
384
385
386
387
388
389 public <V0> SortedSetMultimapBuilder<K0, V0> treeSetValues(final Comparator<V0> comparator) {
390 checkNotNull(comparator, "comparator");
391 return new SortedSetMultimapBuilder<K0, V0>() {
392 @Override
393 public <K extends K0, V extends V0> SortedSetMultimap<K, V> build() {
394 return Multimaps.newSortedSetMultimap(
395 MultimapBuilderWithKeys.this.<K, V>createMap(),
396 new TreeSetSupplier<V>(comparator));
397 }
398 };
399 }
400
401
402
403
404 public <V0 extends Enum<V0>> SetMultimapBuilder<K0, V0> enumSetValues(
405 final Class<V0> valueClass) {
406 checkNotNull(valueClass, "valueClass");
407 return new SetMultimapBuilder<K0, V0>() {
408 @Override
409 public <K extends K0, V extends V0> SetMultimap<K, V> build() {
410
411
412 @SuppressWarnings({"unchecked", "rawtypes"})
413 Supplier<Set<V>> factory = (Supplier) new EnumSetSupplier<V0>(valueClass);
414 return Multimaps.newSetMultimap(
415 MultimapBuilderWithKeys.this.<K, V>createMap(),
416 factory);
417 }
418 };
419 }
420 }
421
422
423
424
425 public abstract <K extends K0, V extends V0> Multimap<K, V> build();
426
427
428
429
430
431 public <K extends K0, V extends V0> Multimap<K, V> build(
432 Multimap<? extends K, ? extends V> multimap) {
433 Multimap<K, V> result = build();
434 result.putAll(multimap);
435 return result;
436 }
437
438
439
440
441 public abstract static class ListMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
442 ListMultimapBuilder() {}
443
444 @Override
445 public abstract <K extends K0, V extends V0> ListMultimap<K, V> build();
446
447 @Override
448 public <K extends K0, V extends V0> ListMultimap<K, V> build(
449 Multimap<? extends K, ? extends V> multimap) {
450 return (ListMultimap<K, V>) super.build(multimap);
451 }
452 }
453
454
455
456
457 public abstract static class SetMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
458 SetMultimapBuilder() {}
459
460 @Override
461 public abstract <K extends K0, V extends V0> SetMultimap<K, V> build();
462
463 @Override
464 public <K extends K0, V extends V0> SetMultimap<K, V> build(
465 Multimap<? extends K, ? extends V> multimap) {
466 return (SetMultimap<K, V>) super.build(multimap);
467 }
468 }
469
470
471
472
473 public abstract static class SortedSetMultimapBuilder<K0, V0> extends SetMultimapBuilder<K0, V0> {
474 SortedSetMultimapBuilder() {}
475
476 @Override
477 public abstract <K extends K0, V extends V0> SortedSetMultimap<K, V> build();
478
479 @Override
480 public <K extends K0, V extends V0> SortedSetMultimap<K, V> build(
481 Multimap<? extends K, ? extends V> multimap) {
482 return (SortedSetMultimap<K, V>) super.build(multimap);
483 }
484 }
485 }